package com.world.business.dict.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpStatus;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.world.business.dict.domain.DictData;
import com.world.business.dict.domain.DictType;
import com.world.business.dict.domain.query.DictGetTreeRequest;
import com.world.business.dict.domain.query.DictTypeAddRequest;
import com.world.business.dict.domain.vo.DictDataVO;
import com.world.business.dict.domain.vo.DictTreeVO;
import com.world.business.dict.mapper.DictDataMapper;
import com.world.business.dict.mapper.DictTypeMapper;
import com.world.business.dict.service.IDictDataService;
import com.world.business.dict.service.IDictTypeService;
import com.world.common.constants.RedisKeyConstants;
import com.world.common.enumeration.DelFlagEnum;
import com.world.common.exception.BusinessException;
import com.world.common.security.SecurityUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 数据字典类型 服务实现类
 * </p>
 *
 * @author 邓驴
 * @since 2023-07-27
 */
@Service
public class DictTypeServiceImpl extends ServiceImpl<DictTypeMapper, DictType> implements IDictTypeService {

    @Resource
    private DictDataMapper dictDataMapper;
    @Resource
    private IDictDataService dictDataService;
    @Resource
    private RedisTemplate<String, DictTreeVO> redisTemplate;

    @Override
    public Long add(DictTypeAddRequest request) {
        LambdaQueryWrapper<DictType> queryWrapper = Wrappers.lambdaQuery(DictType.class);
        queryWrapper.eq(DictType::getDictName, request.getDictName())
                .or()
                .eq(DictType::getDictType, request.getDictType());
        List<DictType> list = this.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(list)) {
            throw new SecurityException("字典名称或字典类型不能重复！");
        }

        DictType build = DictType.builder()
                .dictName(request.getDictName())
                .dictType(request.getDictType())
                .status("0")
                .remark(request.getRemark())
                .delFlag(DelFlagEnum.NORMAL.getCode())
                .createBy(SecurityUtils.getLoginUser().getName())
                .createTime(LocalDateTime.now())
                .createById(SecurityUtils.getLoginUser().getId())
                .build();
        this.save(build);

        //清除缓存
        redisTemplate.delete(RedisKeyConstants.DICT_LIST_KEY);
        return build.getId();
    }

    @Override
    public List<DictTreeVO> tree(DictGetTreeRequest request) {
        List<DictTreeVO> tree = redisTemplate.boundListOps(RedisKeyConstants.DICT_LIST_KEY).range(0, redisTemplate.boundListOps(RedisKeyConstants.DICT_LIST_KEY).size());
        if (CollectionUtil.isEmpty(tree)) {
            tree = getTree(request);
            tree.forEach(i -> redisTemplate.boundListOps(RedisKeyConstants.DICT_LIST_KEY).rightPush(i));
        }
        return tree;
    }

    /**
     * 获取字典树
     *
     * @param request 请求参数
     * @return {@link List<DictTreeVO>}
     * @author WangYX
     * @date 2023/07/28 14:59
     */
    private List<DictTreeVO> getTree(DictGetTreeRequest request) {
        //数据字典类型
        LambdaQueryWrapper<DictType> queryWrapper = Wrappers.lambdaQuery(DictType.class);
        queryWrapper.eq(request.getId() != null, DictType::getId, request.getId());
        queryWrapper.eq(StrUtil.isNotBlank(request.getDictName()), DictType::getId, request.getId());
        queryWrapper.eq(StrUtil.isNotBlank(request.getDictType()), DictType::getId, request.getId());
        queryWrapper.eq(DictType::getDelFlag, DelFlagEnum.NORMAL.getCode());
        List<DictType> dictTypes = this.baseMapper.selectList(queryWrapper);

        List<Long> ids = dictTypes.stream().map(DictType::getId).collect(Collectors.toList());
        //返回值
        List<DictTreeVO> tree = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(ids)) {
            tree = BeanUtil.copyToList(dictTypes, DictTreeVO.class);
            LambdaQueryWrapper<DictData> lambdaQuery = Wrappers.lambdaQuery(DictData.class);
            lambdaQuery.eq(DictData::getDelFlag, DelFlagEnum.NORMAL.getCode());
            lambdaQuery.in(DictData::getDictTypeId, ids);
            List<DictData> dictDataList = dictDataMapper.selectList(lambdaQuery);
            if (CollectionUtil.isNotEmpty(dictDataList)) {
                List<DictDataVO> dictDataVOS = BeanUtil.copyToList(dictDataList, DictDataVO.class);
                Map<Long, List<DictDataVO>> map = dictDataVOS.stream().collect(Collectors.groupingBy(DictDataVO::getDictTypeId));
                tree.forEach(i -> i.setSubs(map.get(i.getId())));
            }
        }
        return tree;
    }

    @Override
    public DictTreeVO get(Long id) {
        List<DictTreeVO> tree = this.tree(new DictGetTreeRequest());
        Optional<DictTreeVO> first = tree.stream().filter(i -> i.getId().equals(id)).findFirst();
        return first.orElse(null);
    }

    @Override
    public void delete(Long id) {
        //删除数据
        List<DictDataVO> dictDataList = dictDataService.getListByDictTypeId(id);
        if (CollectionUtil.isNotEmpty(dictDataList)) {
            throw new BusinessException(HttpStatus.HTTP_BAD_REQUEST, "数据类型下存在数据，请先清空数据！");
        }
        DictType build = DictType.builder().id(id).delFlag(DelFlagEnum.DELETE.getCode()).build();
        this.updateById(build);

        //清除缓存
        redisTemplate.delete(RedisKeyConstants.DICT_LIST_KEY);
    }

}
